<?php
/**
 * Push.php
 * Notes:推送
 * author: chen
 * DateTime: 2023/2/7 11:49
 * @package app\Common\Push
 */

namespace Xtsb\Cims\Push;

use Xtsb\Cims\Exception\ApiErrorDesc;
use Xtsb\Cims\Exception\ApiException;
use Xtsb\Cims\Ws;
use think\facade\Db;
use think\facade\Log;

class Push
{
  public $platform;

  private $data;
  private $uids;
  private $path;

  //通知类型配置
  const NoticeConfig = [
    'wx_notify_auth' => 'wx_notify',//审批通知
    'wx_notify_finish' => 'wx_notify_finish',//审批完成通知
    'wx_notify_back' => 'wx_notify',//审批驳回通知
    'wx_notify_task' => 'wx_notify',//任务通知
    'wx_meeting_info' => 'wx_meeting_notice',//会议通知
  ];

  public function __construct($platform = 'cims')
  {
    $this->platform = $platform;
  }

  //推送对象
  public function uids(array $uids)
  {
    $this->uids = Db::name('staff_access')->alias('g')
      ->field('u.unionid,g.id uid,s.name')
      ->leftJoin('staff s', 's.id = g.staff_id')
      ->leftJoin('user u', 'u.uid = s.uid')
      ->whereIn('g.id', $uids)
      ->select()->toArray();
    return $this;
  }

  //通知标题，可以是业务类型，或者是其他内容，示例： 审核类型：合同申请
  public function title($title = '')
  {
    $this->data['title'] = $title;
    return $this;
  }

  //业务地址
  public function redirect($redirectAction = '')
  {
    $this->data['redirect_action'] = $redirectAction;
    return $this;
  }

  //推送内容
  public function content($content = '')
  {
    $this->data['content'] = $content;//普通推送
    $this->data['status'] = $content;//审批完成
    $this->data['opinion'] = $content;//驳回
    return $this;
  }

  //推送备注
  public function remark($remark = '')
  {
    $this->data['remark'] = $remark;
    return $this;
  }

  //会议地址
  public function address($address = '')
  {
    $this->data['address'] = $address;
    return $this;
  }

  //任务推送单号信息
  public function orderNo($orderNo = '', $orderType = '')
  {
    $this->data['order_no'] = $orderNo;
    $this->data['order_type'] = $orderType;
    return $this;
  }

  //通知类型
  public function noticeType($noticeType = '')
  {
    if (!isset(self::NoticeConfig[$noticeType])) {
      throw new ApiException(ApiErrorDesc::ERROR_DEFAULT, '通知类型：【' . $noticeType . '】不存在');
    }
    $this->data['action'] = self::NoticeConfig[$noticeType];
    $this->path = '/api_' . $noticeType;

    $this->data['time'] = date('Y-m-d H:i:s');//推送时间
    $this->data['create_time'] = $this->data['time'];//推送时间
    return $this;
  }

  /**
   * 向保险系统发送微信推送
   * @param string $unionid 用户的unionid，如果不存在，无法进入该系统
   * @param string $title 通知标题，可以是业务类型，或者是其他内容，示例： 审核类型：合同申请
   * @param string $redirect_action 通过通知系统带回的重定向信息，格式为： 多个：action-key1-value1-key2-value2，示例：ca_detail-id-27
   * @param string $content 申请业务的简要描述，示例：提交人：项目部 王五<br>合同名称：xxxxx合同
   * @param string $time 时间信息，为业务提交时间，示例：2020-04-23 18:00:00提交
   * @param string $remark 备注信息，示例：请尽快处理  或者  已经停留3天，请尽快处理
   */
  public function wechatNotice()
  {
    $result = [];
    $access = new WechatPush();
    foreach ($this->uids as $uids) {
      if (empty($uids['unionid'])) {
//        return ['code' => 1, 'message' => '用户未配置微信推送'];
        Log::channel('push')->info('wechat 用户未配置微信推送：{data}', ['data' => $uids['uid'] . '--' . $uids['name']]);
        continue;
      }
      $this->data['unionid'] = $uids['unionid'];
      $this->data['uid'] = $uids['uid'];
      Log::channel('push')->info('wechat 数据提交：{data}', ['data' => json_encode($this->data, JSON_UNESCAPED_UNICODE)]);

      $res = $access->encryptRequest($this->data, $this->path);

      Log::channel('push')->info('wechat 数据返回：{data}', ['data' => json_encode($res, JSON_UNESCAPED_UNICODE)]);
      $result[] = $res;
      unset($res);
    }

    return $result;
  }

  /**
   * 推送 返回结果不为空，则继续微信推送
   * @param $uid
   * @param $title
   * @param $sub_title
   * @param $data_url
   * @param $url
   * @param $type
   * @return array|mixed|string
   * @throws \think\db\exception\DataNotFoundException
   * @throws \think\db\exception\DbException
   * @throws \think\db\exception\ModelNotFoundException
   */
  public function appPush($uid, $title, $sub_title, $data_url, $url = null, $type = null, $isCuid = true)
  {
//		return false;
//    $uid = input('uid', $uid);
//    $title = input('title', $title);
//    $sub_title = input('sub_title', $sub_title);
//    $data_url = input('data_url', $data_url);
//    $url = input('url', $url);

    // 切割url
    if (!$url && strlen($data_url)) {
      $urlArr = explode('?', $data_url);
      $urlArr[0] && $urlArr = explode('?', $urlArr[0]);
      $url = $urlArr[0];
    }

    // 推送app端需要的数据
    $data = [
      'uid' => $uid,
      'title' => $title,
      'sub_title' => $sub_title,
      'data_url' => $data_url,
      'url' => $url,
      'type' => $type,
    ];


    if ($isCuid) {
      $info = Db::name('user')
        ->alias('u')
        ->field('u.*,t2.client_id,t2.type')
        ->leftJoin('user_client t2', 't2.uid = u.uid')
        ->leftJoin('staff s', 's.uid = u.uid')
        ->leftJoin('staff_access sa', 'sa.staff_id = s.id')
        ->where('sa.id', $uid)
        ->find();
      if (!$info) {
        return '';
      }
      $current = date('Y-m-d h:i:s');
      $second = abs(strtotime($current) - strtotime($info['app_push_time']));
//    dump($second);die;
      //1分钟之内不持续推送
      if ($second < 30) {
        return '';
      }

      $update['app_push_time'] = $current;
      $update['push_count'] = Db::raw('push_count+1');


      $pushInfo['client_id'] = $info['client_id'];
      $pushInfo['type'] = $info['type'];

      $content = (new GPush())->pushToSingleByCid($data, $pushInfo);
      if ($content) {
        // 推送成功
        if (!$content['code']) {
          $update['push_count_succ'] = Db::raw('push_count_succ+1');
          Db::name('user')
            ->where('uid', $info['uid'])
            ->update($update);
          return $content;
        } else {
          // 推送失败
          $update['push_content'] = $content;
          \think\facade\Db::name('user')
            ->json(['push_content'])
            ->where('uid', $info['uid'])
            ->update($update);
          return '';
        }
      } else {
        // 推送失败
        \think\facade\Db::name('user')
          ->where('uid', $info['uid'])
          ->update($update);
//      return ['code' => 1, 'msg' => '无推送操作'];
        return '';
      }
    } else {

      $info = Db::name('user_client')
        ->field('client_id,type')
        ->whereNull('cuid')
        ->where('uid', $uid)
        ->find();

      $pushInfo['client_id'] = $info['client_id'];
      $pushInfo['type'] = $info['type'];

      $content = (new GPush())->pushToSingleByCid($data, $pushInfo);

      return $content;
    }


  }


  /**
   * Notes:PC页面推送
   * Author: chenweizhe
   * DateTime: 2023/12/18 20:32
   * @return void|bool
   */
  public function webPush()
  {
    try {
//      $errCode = 1;
//      $errMsg = '网络错误';
//      // 建立socket连接到内部推送端口
//      $client = stream_socket_client('tcp://127.0.0.1:5678', $errCode, $errMsg, 10);
//
//      foreach ($this->uids as $uids) {
//        // 推送的数据，包含uid字段，表示是给这个uid推送
//        $this->data['uid'] = $uids['uid'];
//        $this->data['tag'] = 'notice';
//        // 发送数据，注意5678端口是Text协议的端口，Text协议需要在数据末尾加上换行符
//        fwrite($client, json_encode($this->data, JSON_UNESCAPED_UNICODE) . "\n");
//      }
//      //断开服务
//      fclose($client);
//
//      ob_clean();
      foreach ($this->uids as $uids) {
        WsPush::push($this->data, $uids['uid']);
      }

      return true;
    } catch (\Exception $exception) {

      Log::channel('push')->info('websocket 推送失败：{data}', ['data' => $exception->getMessage()]);

    }

  }

}
